/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2013        */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be        */
/* attached to the FatFs via a glue function rather than modifying it.   */
/* This is an example of glue functions to attach various exsisting      */
/* storage control module to the FatFs module with a defined API.        */
/*-----------------------------------------------------------------------*/

#include "diskio.h"		/* FatFs lower layer API */
#include "ff.h"
#include "stm32f10x.h"
#include "sfud.h"



/* 为每个设备定义一个物理编号 */
#define ATA			    0     // 预留SD卡使用
#define SPI_FLASH		1     // 外部SPI Flash

/*-----------------------------------------------------------------------*/
/* 获取设备状态                                                          */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (BYTE pdrv)
{
	extern bool sfud_read_sfdp(sfud_flash *flash);
	
	DSTATUS status = STA_NOINIT;
	sfud_flash *flash;
	
	switch (pdrv) {
		case ATA:	/* SD CARD */
			break;
    
		case SPI_FLASH:      // 使用外部SPI作为存储设备  
      /* SPI Flash状态检测：读取SPI Flash 设备ID */
		    flash = sfud_get_device(SFUD_W25Q64CV_DEVICE_INDEX);//Harmlink
		    sfud_read_sfdp(flash);
			if(((flash->chip).type_id == 0x40) &&((flash->chip).capacity_id == 0x17))
			{
			/* 设备ID读取结果正确 */
				status &= ~STA_NOINIT;
			}
			else
			{
			/* 设备ID读取结果错误 */
				status = STA_NOINIT;;
			}
			break;

		default:
			status = STA_NOINIT;
	}
	return status;
}

/*-----------------------------------------------------------------------*/
/* 设备初始化                                                            */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (BYTE pdrv)
{
	uint16_t i;
	DSTATUS status = STA_NOINIT;	
	switch (pdrv) {
		case ATA:	         /* SD CARD */
			break;
		case SPI_FLASH:    /* SPI Flash */ 
      /* 初始化SPI Flash */
			sfud_device_init(sfud_get_device(SFUD_W25Q64CV_DEVICE_INDEX));//Harmlink
      /* 延时一小段时间 */
			i=500;
			while(--i);	
      /* 唤醒SPI Flash */
      /* 获取SPI Flash芯片状态 */
			status=disk_status(SPI_FLASH);//Harmlink
			break;
      
		default:
			status = STA_NOINIT;
	}
	return status;
}


/*-----------------------------------------------------------------------*/
/* 读扇区：读取扇区内容到指定存储区                                              */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
	BYTE pdrv,		/* 设备物理编号(0..) */
	BYTE *buff,		/* 数据缓存区 */
	DWORD sector,	/* 扇区首地址 */
	UINT count		/* 扇区个数(1..128) */
)
{
	DRESULT status = RES_PARERR;
	switch (pdrv) {
		case ATA:	/* SD CARD */
			break;
    
		case SPI_FLASH:
      /* 扇区偏移2MB，外部Flash文件系统空间放在SPI Flash后面6MB空间 */
			sector+=514;      
			sfud_read(sfud_get_device(SFUD_W25Q64CV_DEVICE_INDEX),sector <<12, count<<12, buff);//Harmlink
		
			status = RES_OK;
			break;
    
		default:
			status = RES_PARERR;
	}
	return status;
}

/*-----------------------------------------------------------------------*/
/* 写扇区：见数据写入指定扇区空间上                                      */
/*-----------------------------------------------------------------------*/
#if _USE_WRITE
DRESULT disk_write (
	BYTE pdrv,			  /* 设备物理编号(0..) */
	const BYTE *buff,	/* 欲写入数据的缓存区 */
	DWORD sector,		  /* 扇区首地址 */
	UINT count			  /* 扇区个数(1..128) */
)
{
  uint32_t write_addr; 
	DRESULT status = RES_PARERR;
	if (!count) {
		return RES_PARERR;		/* Check parameter */
	}

	switch (pdrv) {
		case ATA:	/* SD CARD */      
			break;

		case SPI_FLASH:
		  /* 扇区偏移2MB，外部Flash文件系统空间放在SPI Flash后面6MB空间 */
			sector+=514;
			write_addr = sector<<12;    
			sfud_erase(sfud_get_device(SFUD_W25Q64CV_DEVICE_INDEX), write_addr, count<<12);//Harmlink
			sfud_write(sfud_get_device(SFUD_W25Q64CV_DEVICE_INDEX), write_addr, count<<12, (u8 *)buff);//Harmlink
			
			status = RES_OK;
			break;
    
		default:
			status = RES_PARERR;
	}
	return status;
}
#endif


/*-----------------------------------------------------------------------*/
/* 其他控制                                                              */
/*-----------------------------------------------------------------------*/

#if _USE_IOCTL
DRESULT disk_ioctl (
	BYTE pdrv,		/* 物理编号 */
	BYTE cmd,		  /* 控制指令 */
	void *buff		/* 写入或者读取数据地址指针 */
)
{
	DRESULT status = RES_PARERR;
	switch (pdrv) {
		case ATA:	/* SD CARD */
			break;
    
		case SPI_FLASH:
			switch (cmd) {
				/* 扇区数量：1536*4096/1024/1024=6(MB) */
				case GET_SECTOR_COUNT:
					*(DWORD * )buff = 1534;		
					break;
				/* 扇区大小  */
				case GET_SECTOR_SIZE :
					*(WORD * )buff = 4096;
					break;
				/* 同时擦除扇区个数 */
				case GET_BLOCK_SIZE :
					*(DWORD * )buff = 1;
					break;        
			}
			status = RES_OK;
			break;
    
		default:
			status = RES_PARERR;
	}
	return status;
}
#endif

__weak DWORD get_fattime(void) {
	/* 返回当前时间戳 */
	return	  ((DWORD)(2015 - 1980) << 25)	/* Year 2015 */
			| ((DWORD)1 << 21)				/* Month 1 */
			| ((DWORD)1 << 16)				/* Mday 1 */
			| ((DWORD)0 << 11)				/* Hour 0 */
			| ((DWORD)0 << 5)				  /* Min 0 */
			| ((DWORD)0 >> 1);				/* Sec 0 */
}

